package com.haotian.crc;

import java.io.UnsupportedEncodingException;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import com.haotian.barcode.BarCodeImgUtil;

/**
 * java ,CRC(8005型，x16+x15+x2+1)
 *
 * CRC16相关计算 CRC-16 x16+x15+x2+1 8005 IBM SDLC encode: utf-8
 */
public class CRC16 {

	public static String getCRCIBM(byte[] bytes) {
		int CRC = 0x00000000;
		int POLYNOMIAL = 0x0000a001;
		int i, j;
		for (i = 0; i < bytes.length; i++) {
			CRC ^= ((int) bytes[i] & 0x000000ff);
			for (j = 0; j < 8; j++) {
				if ((CRC & 0x00000001) != 0) {
					CRC >>= 1;
					CRC ^= POLYNOMIAL;
				} else {
					CRC >>= 1;
				}
			}
		}
		return Integer.toHexString(CRC);
	}

	public static String getCRCMODBUS(byte[] bytes) {
		int CRC = 0x0000ffff;
		int POLYNOMIAL = 0x0000a001;
		int i, j;
		for (i = 0; i < bytes.length; i++) {
			CRC ^= ((int) bytes[i] & 0x000000ff);
			for (j = 0; j < 8; j++) {
				if ((CRC & 0x00000001) != 0) {
					CRC >>= 1;
					CRC ^= POLYNOMIAL;
				} else {
					CRC >>= 1;
				}
			}
		}
		return Integer.toHexString(CRC);
	}

	public static int checkSum(byte[] bytes) {
		int crc = 0;
		int n = 0;
		if (bytes.length > 0) {
			while (n < bytes.length) {
				for (int i = 128; i != 0; i /= 2) {
					if ((crc & 0x8000) != 0) {
						crc *= 2;
						crc ^= 98309;
					} else {
						crc *= 2;
					}

					if ((bytes[n] & i) != 0) {
						crc ^= 98309;
					}
				}

				n++;
			}
		}
		return crc;
	}

	public static byte[] evalInt(int data) {
		byte[] bytes = new byte[2];
		String crc = Integer.toHexString(data);
		int i = 2;
		while (i <= 4) {
			if (crc.length() + 2 > i) {
				int start = crc.length() - i;
				start = start <= 0 ? 0 : start;
				bytes[(2 - i / 2)] = Integer.valueOf(crc.substring(start, crc.length() - i + 2), 16).byteValue();
			} else {
				bytes[(2 - i / 2)] = 0;
			}
			i += 2;
		}
		return bytes;
	}

	public static byte[] crc16(byte[] bytes) {
		return evalInt(checkSum(bytes));
	}

	public static boolean checkCRC(byte[] data) throws Exception {
		byte[] temp = new byte[data.length - 4];

		System.arraycopy(data, 0, temp, 0, data.length - 4);
		byte[] crc = crc16(temp);

		temp = new byte[2];
		temp[0] = data[(data.length - 4)];
		temp[1] = data[(data.length - 3)];
		int a = Integer.valueOf(new String(temp), 16).intValue();
		temp[0] = data[(data.length - 2)];
		temp[1] = data[(data.length - 1)];
		int b = Integer.valueOf(new String(temp), 16).intValue();
		return (a == (crc[0] & 0xFF)) && (b == (crc[1] & 0xFF));
	}

	// public static void main(String[] args) throws Exception {
	// String txt = "TestPDFText";
	// byte[] data = txt.getBytes("ascii");
	// System.out.println("数据:"+txt+",MODBUS结果:"+CRC16.getCRCMODBUS(data));
	// System.out.println("数据:"+txt+",IBM结果:"+CRC16.getCRCIBM(data));
	// System.out.println("数据:"+txt+",航信函数结果:"+Hex.encodeHexString(CRC16.crc16(data)));
	// }

	public static void main(String[] args) throws UnsupportedEncodingException {
		String info ="中移互联网有限公司</>91440106MA59AKEH1Y</>广州市天河区高唐路333号自编1.1栋020-66600008</>中国农业银行股份有限公司广州南方基地支行44037801040001891</>";
		
		String crc = Hex.encodeHexString(CRC16.crc16(info.getBytes("UTF-8"))).toUpperCase();
		
		String base64Str = Base64.encodeBase64String((info+crc).getBytes("UTF-8"));
		
		String text = "$01"+base64Str + "\r\n$";
		System.out.println("CRC："+crc);
		System.out.println("BASE64:"+base64Str);
		System.out.println("CODE_STRING:"+text);
		
		BarCodeImgUtil.toFile(text, "c://", "mingpian",200,200);
		
		
	}

}
